#[allow(dead_code)]
#[cxx::bridge]
pub mod client {
    unsafe extern "C++" {
        include!("carla/src/wrapper.h");

        type Client;

        fn new_client(host: &str, port: u16, worker_threads: u32) -> UniquePtr<Client>;

        fn set_timeout(self: Pin<&mut Client>, milliseconds: u32);

        fn get_world(self: &Client) -> Result<UniquePtr<World>>;

        fn load_world(
            self: Pin<&mut Client>,
            map_name: &str,
            reset_settings: bool,
        ) -> Result<UniquePtr<World>>;

        fn generate_open_drive_world(
            self: Pin<&mut Client>,
            opendrive: &str,
            vertex_distance: f64,
            max_road_length: f64,
            wall_height: f64,
            additional_width: f64,
            smooth_junctions: bool,
            enable_mesh_visibility: bool,
            enable_pedestrian_navigation: bool,
            reset_settings: bool,
        ) -> Result<UniquePtr<World>>;

        fn reload_world(self: Pin<&mut Client>, reset_settings: bool) -> Result<UniquePtr<World>>;

        type World;

        fn get_snapshot(self: &World) -> Result<UniquePtr<WorldSnapshot>>;

        fn get_map(self: &World) -> Result<UniquePtr<Map>>;

        fn spawn_actor(
            self: Pin<&mut World>,
            blueprint: &str,
            x: f32,
            y: f32,
            z: f32,
            pitch: f32,
            yaw: f32,
            roll: f32,
        ) -> Result<UniquePtr<Actor>>;

        fn get_actor(self: &World, id: u32) -> Result<UniquePtr<Actor>>;

        fn spawn_vehicle(
            self: Pin<&mut World>,
            vehicle_type: &str,
            x: f32,
            y: f32,
            z: f32,
            pitch: f32,
            yaw: f32,
            roll: f32,
        ) -> Result<UniquePtr<Vehicle>>;

        fn get_vehicle(self: &World, id: u32) -> Result<UniquePtr<Vehicle>>;

        fn get_vehicle_by_role(self: &World, role_name: &str) -> Result<UniquePtr<Vehicle>>;

        fn destroy_actor_by_id(self: Pin<&mut World>, id: u32) -> Result<bool>;

        fn create_gnss(
            self: Pin<&mut World>,
            parent_id: u32,
            x: f32,
            y: f32,
            z: f32,
            pitch: f32,
            yaw: f32,
            roll: f32,
            sensor_tick: f32,
        ) -> Result<UniquePtr<GNSS>>;

        fn create_camera(
            self: Pin<&mut World>,
            parent_id: u32,
            x: f32,
            y: f32,
            z: f32,
            pitch: f32,
            yaw: f32,
            roll: f32,
            fov: f32,
            image_size_x: u32,
            image_size_y: u32,
            iso: f32,
            gamma: f32,
            shutter_speed: f32,
            sensor_tick: f32,
        ) -> Result<UniquePtr<Camera>>;

        fn create_collision_detector(
            self: Pin<&mut World>,
            parent_id: u32,
            x: f32,
            y: f32,
            z: f32,
            pitch: f32,
            yaw: f32,
            roll: f32,
        ) -> Result<UniquePtr<CollisionDetector>>;

        fn create_lane_invasion_detector(
            self: Pin<&mut World>,
            parent_id: u32,
            x: f32,
            y: f32,
            z: f32,
            pitch: f32,
            yaw: f32,
            roll: f32,
        ) -> Result<UniquePtr<LaneInvasionDetector>>;

        type WorldSnapshot;

        fn get_running_time(self: &WorldSnapshot) -> u64;

        fn get_system_time(self: &WorldSnapshot) -> u64;

        fn find_actor_snapshot(self: &WorldSnapshot, id: u32) -> UniquePtr<ActorSnapshot>;

        fn get_actor_ids(self: &WorldSnapshot) -> Vec<u32>;

        type Map;

        fn get_name(self: &Map) -> String;

        type LaneInvasionDetector;

        fn get_id(self: &LaneInvasionDetector) -> u32;

        fn get_event(self: Pin<&mut LaneInvasionDetector>) -> UniquePtr<LaneInvasionEvent>;

        type LaneInvasionEvent;

        fn get_timestamp(self: &LaneInvasionEvent) -> u64;

        fn get_lane_change(self: &LaneInvasionEvent) -> Vec<i32>;

        type CollisionDetector;

        fn get_id(self: &CollisionDetector) -> u32;

        fn get_event(self: Pin<&mut CollisionDetector>) -> UniquePtr<CollisionEvent>;

        type CollisionEvent;

        fn get_timestamp(self: &CollisionEvent) -> u64;

        fn get_other_actor(self: &CollisionEvent) -> UniquePtr<Actor>;

        fn get_normal_impulse(self: &CollisionEvent) -> [f32; 3];

        type Camera;

        fn get_id(self: &Camera) -> u32;

        fn get_image(self: Pin<&mut Camera>) -> UniquePtr<Image>;

        type Image;

        fn get_timestamp(self: &Image) -> u64;

        fn get_width(self: &Image) -> u32;

        fn get_height(self: &Image) -> u32;

        fn get_fov_angle(self: &Image) -> f32;

        fn get_bgra_pixels(self: &Image) -> &[u8];

        type GNSS;

        fn get_id(self: &GNSS) -> u32;

        fn get_localization(self: Pin<&mut GNSS>) -> UniquePtr<Localization>;

        type Localization;

        fn get_timestamp(self: &Localization) -> u64;

        fn get_lla(self: &Localization) -> [f64; 3];

        fn get_location(self: &Localization) -> [f32; 3];

        fn get_rotation(self: &Localization) -> [f32; 3];

        type Vehicle;

        fn get_id(self: &Vehicle) -> u32;

        fn get_type_id(self: &Vehicle) -> String;

        fn destroy(self: Pin<&mut Vehicle>) -> Result<bool>;

        fn enable_carsim(self: Pin<&mut Vehicle>, simfile_path: &str) -> Result<()>;

        fn set_transform(
            self: Pin<&mut Vehicle>,
            x: f32,
            y: f32,
            z: f32,
            pitch: f32,
            yaw: f32,
            roll: f32,
        ) -> Result<()>;

        fn apply_control(
            self: Pin<&mut Vehicle>,
            throttle: f32,
            steer: f32,
            brake: f32,
            hand_brake: bool,
            reverse: bool,
            manual_gear_shift: bool,
            gear: i32,
        );

        type Actor;

        fn get_id(self: &Actor) -> u32;

        fn get_type_id(self: &Actor) -> String;

        fn destroy(self: Pin<&mut Actor>) -> Result<bool>;

        fn get_semantic_tags(self: &Actor) -> Vec<u8>;

        fn get_bounding_box(self: &Actor) -> [f32; 9];

        type ActorSnapshot;

        fn get_id(self: &ActorSnapshot) -> u32;

        fn get_location(self: &ActorSnapshot) -> [f32; 3];

        fn get_rotation(self: &ActorSnapshot) -> [f32; 3];

        fn get_velocity(self: &ActorSnapshot) -> [f32; 3];

        fn get_angular_velocity(self: &ActorSnapshot) -> [f32; 3];

        fn get_acceleration(self: &ActorSnapshot) -> [f32; 3];

        fn get_control(self: &ActorSnapshot) -> UniquePtr<Control>;

        fn get_speed_limit(self: &ActorSnapshot) -> f32;

        fn has_traffic_light(self: &ActorSnapshot) -> bool;

        fn get_traffic_light_id(self: &ActorSnapshot) -> u32;

        fn get_traffic_light_state(self: &ActorSnapshot) -> i32;

        type Control;

        fn get_throttle(self: &Control) -> f32;

        fn get_steer(self: &Control) -> f32;

        fn get_brake(self: &Control) -> f32;

        fn get_hand_brake(self: &Control) -> bool;

        fn get_reverse(self: &Control) -> bool;

        fn get_manual_gear_shift(self: &Control) -> bool;

        fn get_gear(self: &Control) -> i32;
    }
}

unsafe impl Send for client::Client {}

unsafe impl Send for client::World {}

unsafe impl Send for client::WorldSnapshot {}

unsafe impl Send for client::LaneInvasionDetector {}

unsafe impl Send for client::LaneInvasionEvent {}

unsafe impl Send for client::CollisionDetector {}

unsafe impl Send for client::CollisionEvent {}

unsafe impl Send for client::Camera {}

unsafe impl Send for client::Image {}

unsafe impl Send for client::GNSS {}

unsafe impl Send for client::Localization {}

unsafe impl Send for client::Vehicle {}

unsafe impl Send for client::Actor {}

unsafe impl Send for client::ActorSnapshot {}
